#define __QYQ_MODULE_CLOCK_C_
#include "qyq_module_clock.h"

// 计算闰年公式
#define leapYear(y) ((y % 4 == 0) && (y % 100 != 0) || (y % 400 == 0))

static uint16_t qyq_module_get_time_day(qyq_module_time_type_t *this)
{
    uint16_t num = 0;
    switch (this->qyq_module_time_data->qyq_module_time_data_mon - 1)
    {
    case 1:
    {
        num = 31;
        break;
    }
    case 2:
    {
        num = 28 + 31;
        break;
    }
    case 3:
    {
        num = 31 + 28 + 31;
        break;
    }
    case 4:
    {
        num = 30 + 31 + 28 + 31;
        break;
    }
    case 5:
    {
        num = 31 + 30 + 31 + 28 + 31;
        break;
    }
    case 6:
    {
        num = 30 + 31 + 30 + 31 + 28 + 31;
        break;
    }
    case 7:
    {
        num = 31 + 30 + 31 + 30 + 31 + 28 + 31;
        break;
    }
    case 8:
    {
        num = 31 + 31 + 30 + 31 + 30 + 31 + 28 + 31;
        break;
    }
    case 9:
    {
        num = 30 + 31 + 31 + 30 + 31 + 30 + 31 + 28 + 31;
        break;
    }
    case 10:
    {
        num = 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31 + 28 + 31;
        break;
    }
    case 11:
    {
        num = 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31 + 28 + 31;
        break;
    }
    case 12:
    {
        num = 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31 + 28 + 31;
        break;
    }
    default:
        break;
    }
    if (leapYear(this->qyq_module_time_data->qyq_module_time_data_year) && (this->qyq_module_time_data->qyq_module_time_data_mon > 2))
    {
        num++;
    }
    num = this->qyq_module_time_data->qyq_module_time_data_mday;

    return num;
}

static uint16_t qyq_module_calc_week(uint16_t yeartxt, uint16_t monthtxt, uint16_t daytxt)
{
    uint16_t weektxt;         // 星期变量
    uint16_t virt_yeartxt;    // 创建一个虚拟适用于基姆拉尔森算式的年变量
    uint16_t virt_monthtxt;   // 创建一个虚拟适用于基姆拉尔森算式的月变量
    virt_yeartxt = yeartxt;   // 赋予给 虚拟年
    virt_monthtxt = monthtxt; // 赋予给 虚拟月
    // 把一月和二月看成是上一年的十三月和十四月， 例： 如果是 2004-1-10 则换算成： 2003-13-10 来代入公式计算。
    if ((1 == monthtxt) || (2 == monthtxt))
    {
        virt_monthtxt += 12; // 产生 13/14
        virt_yeartxt -= 1;   // 赋予给 虚拟年
    }
    // 基姆拉尔森算式 此公式是 0~6 表示星期一至星期日
    weektxt = (daytxt + 2 * virt_monthtxt + 3 * (virt_monthtxt + 1) / 5 + virt_yeartxt + virt_yeartxt / 4 - virt_yeartxt / 100 + virt_yeartxt / 400) % 7;
    weektxt += 1; // 转换为 1~7 表示星期一至星期日
    return weektxt;
}

static int8_t qyq_module_time_count(qyq_module_time_type_t *this)
{
    if (this == null)
    {
        return -1;
    }

    this->qyq_module_time_data->qyq_module_time_data_sec++;
    if (this->qyq_module_time_data->qyq_module_time_data_sec > 59)
    {
        this->qyq_module_time_data->qyq_module_time_data_sec = 0;
        this->qyq_module_time_data->qyq_module_time_data_min++;
        if (this->qyq_module_time_data->qyq_module_time_data_min > 59)
        {
            this->qyq_module_time_data->qyq_module_time_data_min = 0;
            this->qyq_module_time_data->qyq_module_time_data_hour++;
            if (this->qyq_module_time_data->qyq_module_time_data_hour > 23)
            {
                this->qyq_module_time_data->qyq_module_time_data_hour = 0;
                this->qyq_module_time_data->qyq_module_time_data_mday++;
                switch (this->qyq_module_time_data->qyq_module_time_data_mon)
                {
                case 1:
                    if (this->qyq_module_time_data->qyq_module_time_data_mday > 31)
                    {
                        this->qyq_module_time_data->qyq_module_time_data_mday = 1;
                        this->qyq_module_time_data->qyq_module_time_data_mon++;
                    }
                    break;
                case 2:
                    if (leapYear(this->qyq_module_time_data->qyq_module_time_data_year))
                    {
                        if (this->qyq_module_time_data->qyq_module_time_data_mday > 29)
                        {
                            this->qyq_module_time_data->qyq_module_time_data_mday = 1;
                            this->qyq_module_time_data->qyq_module_time_data_mon++;
                        }
                    }
                    else
                    {
                        if (this->qyq_module_time_data->qyq_module_time_data_mday > 28)
                        {
                            this->qyq_module_time_data->qyq_module_time_data_mday = 1;
                            this->qyq_module_time_data->qyq_module_time_data_mon++;
                        }
                    }
                    break;
                case 3:
                    if (this->qyq_module_time_data->qyq_module_time_data_mday > 31)
                    {
                        this->qyq_module_time_data->qyq_module_time_data_mday = 1;
                        this->qyq_module_time_data->qyq_module_time_data_mon++;
                    }
                    break;
                case 4:
                    if (this->qyq_module_time_data->qyq_module_time_data_mday > 30)
                    {
                        this->qyq_module_time_data->qyq_module_time_data_mday = 1;
                        this->qyq_module_time_data->qyq_module_time_data_mon++;
                    }
                    break;
                case 5:
                    if (this->qyq_module_time_data->qyq_module_time_data_mday > 31)
                    {
                        this->qyq_module_time_data->qyq_module_time_data_mday = 1;
                        this->qyq_module_time_data->qyq_module_time_data_mon++;
                    }
                    break;
                case 6:
                    if (this->qyq_module_time_data->qyq_module_time_data_mday > 30)
                    {
                        this->qyq_module_time_data->qyq_module_time_data_mday = 1;
                        this->qyq_module_time_data->qyq_module_time_data_mon++;
                    }
                    break;
                case 7:
                    if (this->qyq_module_time_data->qyq_module_time_data_mday > 31)
                    {
                        this->qyq_module_time_data->qyq_module_time_data_mday = 1;
                        this->qyq_module_time_data->qyq_module_time_data_mon++;
                    }
                    break;
                case 8:
                    if (this->qyq_module_time_data->qyq_module_time_data_mday > 31)
                    {
                        this->qyq_module_time_data->qyq_module_time_data_mday = 1;
                        this->qyq_module_time_data->qyq_module_time_data_mon++;
                    }
                    break;
                case 9:
                    if (this->qyq_module_time_data->qyq_module_time_data_mday > 30)
                    {
                        this->qyq_module_time_data->qyq_module_time_data_mday = 1;
                        this->qyq_module_time_data->qyq_module_time_data_mon++;
                    }
                    break;
                case 10:
                    if (this->qyq_module_time_data->qyq_module_time_data_mday > 31)
                    {
                        this->qyq_module_time_data->qyq_module_time_data_mday = 1;
                        this->qyq_module_time_data->qyq_module_time_data_mon++;
                    }
                    break;
                case 11:
                    if (this->qyq_module_time_data->qyq_module_time_data_mday > 30)
                    {
                        this->qyq_module_time_data->qyq_module_time_data_mday = 1;
                        this->qyq_module_time_data->qyq_module_time_data_mon++;
                    }
                    break;
                case 12:
                    if (this->qyq_module_time_data->qyq_module_time_data_mday > 31)
                    {
                        this->qyq_module_time_data->qyq_module_time_data_mday = 1;
                        this->qyq_module_time_data->qyq_module_time_data_mon++;
                    }
                    break;
                }
                if (this->qyq_module_time_data->qyq_module_time_data_mon > 12)
                {
                    this->qyq_module_time_data->qyq_module_time_data_year++;
                }
                this->qyq_module_time_data->qyq_module_time_data_wday = qyq_module_calc_week(this->qyq_module_time_data->qyq_module_time_data_year, this->qyq_module_time_data->qyq_module_time_data_mon, this->qyq_module_time_data->qyq_module_time_data_mday);
                this->qyq_module_time_data->qyq_module_time_data_yday = qyq_module_get_time_day(this);
            }
        }
    }

    return 0;
}

int8_t qyq_module_get_time(struct qyq_module_time_type *this, qyq_module_time_data_t *qyq_module_time_data)
{
    if (this == null)
    {
        return -1;
    }

    if (qyq_module_time_data == null)
    {
        return -1;
    }

    qyq_module_time_data->qyq_module_time_data_sec = this->qyq_module_time_data->qyq_module_time_data_sec;
    qyq_module_time_data->qyq_module_time_data_min = this->qyq_module_time_data->qyq_module_time_data_min;
    qyq_module_time_data->qyq_module_time_data_hour = this->qyq_module_time_data->qyq_module_time_data_hour;
    qyq_module_time_data->qyq_module_time_data_mday = this->qyq_module_time_data->qyq_module_time_data_mday;
    qyq_module_time_data->qyq_module_time_data_mon = this->qyq_module_time_data->qyq_module_time_data_mon;
    qyq_module_time_data->qyq_module_time_data_year = this->qyq_module_time_data->qyq_module_time_data_year;
    qyq_module_time_data->qyq_module_time_data_wday = this->qyq_module_time_data->qyq_module_time_data_wday;
    qyq_module_time_data->qyq_module_time_data_yday = this->qyq_module_time_data->qyq_module_time_data_yday;

    return 0;
}

int8_t qyq_module_set_time(struct qyq_module_time_type *this, qyq_module_time_data_t *qyq_module_time_data)
{
    if (this == null)
    {
        return -1;
    }
    if (qyq_module_time_data == null)
    {
        return -1;
    }
    this->qyq_module_time_data->qyq_module_time_data_sec = qyq_module_time_data->qyq_module_time_data_sec;
    this->qyq_module_time_data->qyq_module_time_data_min = qyq_module_time_data->qyq_module_time_data_min;
    this->qyq_module_time_data->qyq_module_time_data_hour = qyq_module_time_data->qyq_module_time_data_hour;
    this->qyq_module_time_data->qyq_module_time_data_mday = qyq_module_time_data->qyq_module_time_data_mday;
    this->qyq_module_time_data->qyq_module_time_data_mon = qyq_module_time_data->qyq_module_time_data_mon;
    this->qyq_module_time_data->qyq_module_time_data_year = qyq_module_time_data->qyq_module_time_data_year;
    this->qyq_module_time_data->qyq_module_time_data_wday = qyq_module_time_data->qyq_module_time_data_wday;
    this->qyq_module_time_data->qyq_module_time_data_yday = qyq_module_time_data->qyq_module_time_data_yday;
    this->qyq_module_time_data->qyq_module_time_data_wday = qyq_module_calc_week(this->qyq_module_time_data->qyq_module_time_data_year, this->qyq_module_time_data->qyq_module_time_data_mon, this->qyq_module_time_data->qyq_module_time_data_mday);
    this->qyq_module_time_data->qyq_module_time_data_yday = qyq_module_get_time_day(this);

    return 0;
}

int8_t qyq_module_time_create(qyq_module_time_type_t *this, qyq_module_time_data_t *qyq_module_time_data)
{
    if (this == null)
    {
        return -1;
    }
    if (qyq_module_time_data == null)
    {
        return -1;
    }

    this->qyq_module_time_data = qyq_module_time_data;

    this->qyq_module_time_data->qyq_module_time_data_sec = 0;
    this->qyq_module_time_data->qyq_module_time_data_min = 0;
    this->qyq_module_time_data->qyq_module_time_data_hour = 0;
    this->qyq_module_time_data->qyq_module_time_data_mday = 1;
    this->qyq_module_time_data->qyq_module_time_data_mon = 1;
    this->qyq_module_time_data->qyq_module_time_data_year = 1900;
    this->qyq_module_time_data->qyq_module_time_data_wday = qyq_module_calc_week(this->qyq_module_time_data->qyq_module_time_data_year, this->qyq_module_time_data->qyq_module_time_data_mon, this->qyq_module_time_data->qyq_module_time_data_mday);
    this->qyq_module_time_data->qyq_module_time_data_yday = qyq_module_get_time_day(this);

    this->qyq_module_time_count = qyq_module_time_count;
    this->qyq_module_get_time = qyq_module_get_time;
    return 0;
}
